﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;


namespace DQYT.HTDZ.BusinessService
{
    /// <summary>
    /// 提供操作EXCEL文件的方法
    /// </summary>
    public class ProcExcel
    {

        /// <summary>
        /// 用FarPoint组件读取EXCEL数据，存储到一个DATATABLE中返回
        /// </summary>
        /// <param name="p_ExcelFile">EXCEL文件名，形如： c:\1.xls</param>
        /// <param name="p_StartSheetIndex">读取哪个工作簿，从1开始数</param>
        /// <param name="p_StartColumnIndex">从哪列开始，从1开始数</param>
        /// <param name="p_StartRowIndex">从哪行开始，从1开始数</param>
        /// <param name="p_DataBaseColumnInRowIndex">第几行标注了对应数据库列的代码，从1开始数</param>
        /// <returns>datatable</returns>
        public static DataTable GetDataTableFromExcel(string p_ExcelFile, int p_StartSheetIndex, int p_StartColumnIndex, int p_StartRowIndex, int p_DataBaseColumnInRowIndex)
        {
            #region 代码实现

            FarPoint.Web.Spread.FpSpread fpSpread1 = ReadExcel(p_ExcelFile);
            DataTable dt = GetDataTableFromFpSpread(fpSpread1, p_StartSheetIndex, p_StartColumnIndex, p_StartRowIndex, p_DataBaseColumnInRowIndex);

            return dt;
            #endregion 代码实现
        }

        /// <summary>
        /// 用FarPoint组件读取EXCEL二进制流，存储到一个DATATABLE中返回
        /// </summary>
        /// <param name="p_ExcelFileStream">EXCEL二进制流 </param>
        /// <param name="p_StartSheetIndex">读取哪个工作簿，从1开始数</param>
        /// <param name="p_StartColumnIndex">从哪列开始，从1开始数</param>
        /// <param name="p_StartRowIndex">从哪行开始，从1开始数</param>
        /// <param name="p_DataBaseColumnInRowIndex">第几行标注了对应数据库列的代码，从1开始数</param>
        /// <returns>datatable</returns>
        public static DataTable GetDataTableFromExcelFileStream(System.IO.Stream p_ExcelFileStream, int p_StartSheetIndex, int p_StartColumnIndex, int p_StartRowIndex, int p_DataBaseColumnInRowIndex)
        {
            #region 代码实现

            FarPoint.Web.Spread.FpSpread fpSpread1 = ReadExcel(p_ExcelFileStream);
            DataTable dt = GetDataTableFromFpSpread(fpSpread1, p_StartSheetIndex, p_StartColumnIndex, p_StartRowIndex, p_DataBaseColumnInRowIndex);

            return dt;
            #endregion 代码实现
        }

        /// <summary>
        /// 固定格式的EXCEL文件可以使用此函数读取数据
        /// 
        /// </summary>
        /// <param name="p_ExcelFile">EXCEL文件名，形如： c:\1.xls</param>
        /// <returns></returns>
        public static DataTable GetExcelData(string p_ExcelFile)
        {
            /* 1行：表的汉字标题
             * 2行：列的序号，1,2,3...这样今后用户数据填的不合格时，可以告诉他第几列的第几行数据有误
             * 3行：列的汉字标题
             * 4行：对应数据库的列代码，导数据时就可以根据这个列代码导入，否则还得另外再写对应文件
                 */
            return GetDataTableFromExcel(p_ExcelFile, 1, 1, 5, 4);

        }

        /// <summary>
        /// 固定格式的EXCEL文件可以使用此函数读取数据
        /// 
        /// </summary>
        /// <param name="p_ExcelFile">EXCEL文件名，形如： c:\1.xls</param>
        /// <returns></returns>
        public static DataTable GetExcelData(System.IO.Stream p_ExcelFileStream)
        {
            /* 1行：表的汉字标题
             * 2行：列的序号，1,2,3...这样今后用户数据填的不合格时，可以告诉他第几列的第几行数据有误
             * 3行：列的汉字标题
             * 4行：对应数据库的列代码，导数据时就可以根据这个列代码导入，否则还得另外再写对应文件
                 */
            return GetDataTableFromExcelFileStream(p_ExcelFileStream, 1, 1, 5, 4);

        }

        /// <summary>
        /// 把一个EXCEL文件数据读取到FarPoint.Web.Spread.FpSpread中
        /// </summary>
        /// <param name="p_ExcelFile">带全路径的一个EXCEL文件，形如： C:\TMP\1.XLS</param>
        /// <returns>FarPoint.Web.Spread.FpSpread</returns>
        private static FarPoint.Web.Spread.FpSpread ReadExcel(string p_ExcelFile)
        {
            FarPoint.Web.Spread.FpSpread fpSpread1 = new FarPoint.Web.Spread.FpSpread();
            bool ret = fpSpread1.OpenExcel(p_ExcelFile);//打开EXCEL文件
            return fpSpread1;
        }

        /// <summary>
        /// 把一个EXCEL文件数据流读取到FarPoint.Web.Spread.FpSpread中
        /// 这个数据流可以使用 FileUpload1.PostedFile.InputStream得到
        /// </summary>
        /// <param name="p_ExcelFileStream">EXCEL文件数据流 ，这个数据流可以使用 FileUpload1.PostedFile.InputStream得到 </param>
        /// <returns>FarPoint.Web.Spread.FpSpread</returns>
        private static FarPoint.Web.Spread.FpSpread ReadExcel(System.IO.Stream p_ExcelFileStream)
        {
            FarPoint.Web.Spread.FpSpread fpSpread1 = new FarPoint.Web.Spread.FpSpread();
            bool ret = fpSpread1.OpenExcel(p_ExcelFileStream);//打开EXCEL文件
            return fpSpread1;
        }


        /// <summary>
        /// 把FarPoint组件中的数据读取到一个DATATABLE中返回
        /// </summary>
        /// <param name="p_FpSpread">FarPoint组件 </param>
        /// <param name="p_StartSheetIndex">读取哪个工作簿，从1开始数</param>
        /// <param name="p_StartColumnIndex">从哪列开始，从1开始数</param>
        /// <param name="p_StartRowIndex">从哪行开始，从1开始数</param>
        /// <param name="p_DataBaseColumnInRowIndex">第几行标注了对应数据库列的代码，从1开始数</param>
        /// <returns>datatable</returns>
        private static DataTable GetDataTableFromFpSpread(FarPoint.Web.Spread.FpSpread p_FpSpread, int p_StartSheetIndex, int p_StartColumnIndex, int p_StartRowIndex, int p_DataBaseColumnInRowIndex)
        {
            #region 代码实现
            /*
             在EXCEL中，建议前几行标准这些信息：
             * 1行：表的汉字标题
             * 2行：列的序号，1,2,3...这样今后用户数据填的不合格时，可以告诉他第几列的第几行数据有误
             * 3行：列的汉字标题
             * 4行：对应数据库的列代码，导数据时就可以根据这个列代码导入，否则还得另外再写对应文件
             */


            FarPoint.Web.Spread.FpSpread fpSpread1 = p_FpSpread;
            FarPoint.Web.Spread.SheetView sheet = fpSpread1.Sheets[p_StartSheetIndex - 1];  //就是这个工作簿的数据

            //这两行是获得该工作簿中最大可能的行数和列数，即使是只设置了各式而没有数据的单元格，这里也会被认作是有校的，
            //所以后面还会根据单元格是否有值来再次判断行是否为空或列是否为空
            int iMaxRowCount = sheet.RowCount;
            int iMaxColCount = sheet.ColumnCount;

            DataTable dt = new DataTable();
            string strValue = "";
            //在这个循环中，根据“对应数据库的列代码”的那一行数据判断列的结尾，并把每一列创建到DataTable中
            for (int i = p_StartColumnIndex - 1; i < iMaxColCount; i++)
            {
                strValue = sheet.Cells[p_DataBaseColumnInRowIndex - 1, i].Text.Trim();
                if (!string.IsNullOrEmpty(strValue))
                {
                    dt.Columns.Add(strValue);
                }
                else
                {
                    break;//该单元格没有数据，说明是列的结尾了
                }
            }


            int iColCount = dt.Columns.Count;

            //读取每一行的数据存入表中，根据第一列是否有值来判断是否到了行结尾
            for (int iRowIndex = p_StartRowIndex - 1; iRowIndex < iMaxRowCount; iRowIndex++)
            {
                strValue = sheet.Cells[iRowIndex, p_StartColumnIndex - 1].Text.Trim();
                if (!string.IsNullOrEmpty(strValue))
                {
                    DataRow dr = dt.NewRow();
                    for (int iColIndex = 0; iColIndex < iColCount; iColIndex++)
                    {
                        strValue = sheet.Cells[iRowIndex, iColIndex + p_StartColumnIndex - 1].Text.Trim();
                        dr[iColIndex] = strValue;
                    }
                    dt.Rows.Add(dr);
                }
                else
                {
                    break;//到了行结尾
                }
            }


            return dt;
            #endregion 代码实现
        }




    }
}
